package com.hangxintong.common.exception;

import lombok.Getter;

/**
 * 客户端异常标记接口。
 * 用于标记{@link ClientException}对象的错误码参数类型,防止错误码串用.
 * @author lvyanfei
 * @date 2021-01-04
 */
public interface ClientErrorCodeMark extends ErrorInfo {

    /**
     * 用户操作异常错误码枚举
     */
    @Getter
    enum Code implements ClientErrorCodeMark {

        /**
         * 参数错误(可以笼统的将所有参数错误都包含在内,并重新定义错误描述,一般用于框架参数自定义错误验证)
         */
        PARAMETER_ERROR(400, "参数错误"),
        UNAUTHORIZED_ERROR(401, "需要授权认证"),
        FORBIDDEN_ERROR(403, "禁止访问"),
        //FORBIDDEN_ERROR("404", "没有找到资源"),
        //FORBIDDEN_ERROR("405", "方法不可用（get/post）"),
        FREQUENTLY(413, "操作过于频繁，请稍候再试")
        ;

        Code(Integer errorCode) {
            this.errorCode = errorCode;
            //this.errorDesc = EnumUtil.getByCode(errorCode,ClientErrorCodeMark.class).getErrorDesc();
        }
        Code(Integer errorCode, String errorDesc) {
            this.errorCode = errorCode;
            this.errorDesc = errorDesc;
        }

        /**
         * 错误码.
         */
        private Integer errorCode;
        /**
         * 错误码对应的外部描述信息,该信息是通过错误码自动获取,并且直接返回给调用方.
         */
        private String errorDesc;
    }

    /**
     * 快速构建一个自定义错误描述错误信息对象.
     * <p>
     *   一般用于相同的错误码,但是不同的错误描述信息(类似).
     *   比如常见的参数错误,但是可以使用参数错误的通用错误码在描述中提示调用者更具体的错误描述.
     * </p>
     * @param desc      新的错误描述
     * @return 使用自定义描述替换原有描述的信息对象副本
     */
    default ClientErrorCodeMark as(String desc) {
        ErrorInfo errorInfo = this;
        return new ClientErrorCodeMark() {
            @Override
            public Integer getErrorCode() {
                return errorInfo.getErrorCode();
            }

            @Override
            public String getErrorDesc() {
                return desc;
            }
        };
    }
}
